#ifndef __LISTCPP__
#define __LISTCPP__

#include <iostream>



template<class T>
class ListCpp
{
    public:

        class ListIterator
        {
            public:

                // default ctor- make empty itrator
                ListIterator();

                //~ListIterator();  no need,we don't use dynamic memmory allocation

                //step to next data node
                ListIterator& operator++(); // ListIterator iter = ++(list.begin())

                //step to previous data node
                ListIterator& operator--();

                // iterators are equal if they have the same target
                bool          operator==(const ListIterator& _other)const;

                // complement of operator==()
                bool          operator!=(const ListIterator& _other)const;

                // return pointer to data in iterator's target,
                // throw exception if no target or target not a data node
                T*           Get() ;

                friend ListIterator ListCpp::Begin();
                friend ListIterator ListCpp::End();

            private:

            //ctor from List c iter ,for use of class ListCpp
             explicit   ListIterator(const ListIter& _other);

                #ifdef _DEBUG
                    //in debug mode we chek if iterator is legal
                    explicit   ListIterator(const ListIter& _otherIter,List* _otherList);
                    List* m_list;//list of the iterator
                #endif //_DEBUG

                ListIter m_iter;//c list iterator
        };

        class ConstListIterator
        {
            public:
                // default ctor- make empty itrator
                ConstListIterator();

                //~ConstListIterator(); no need,we don't use dynamic memmory allocation

                // create constant iterator from regular iterator
                explicit   ConstListIterator(const ListIterator& other);

                //step to next data node
                ConstListIterator operator++();

                //step to previous data node
                ConstListIterator operator--();

                // iterators are equal if they have the same target
                bool              operator==(const ConstListIterator& _other)const;

                // complement of operator==()
                bool              operator!=(const ConstListIterator& _other)const;

                // assign regular iterator to constant iterator
                ConstListIterator&operator=(const ListIterator& _other);

                // return pointer to data in iterator's target,
                // throw exception if no target or target not a data node
                const T* Get() ;

            private:

                ConstListIterator(const ListIter& _other);

                #ifdef _DEBUG
                    explicit   ListIterator(const ListIter& _otherIter,List* _otherList);
                    List* m_list;               /** list of the iterator*/
                #endif //_DEBUG

                ListIter m_iter;
        };

        // default ctor- make empty list
        ListCpp();

        //Default dtor
        ~ListCpp();

        //Copy ctor
        explicit ListCpp(const ListCpp& other);

        //return iterator to first element
        ListIterator    Begin();

        //return const iterator to first element
        ConstListIterator    Begin()const;

        //return iterator to the past-the-end element in the list container
        ListIterator    End();

        //return const iterator to the past-the-end element in the list container
        ConstListIterator    End()const;

        // insert before target of iterator
        // if iterator target is not a data node or the End(),behavior is undefined
        ListIterator&   Insert(const ListIterator& _it,T* _data);

        // Remove iterator _it, return next iterator after the romved one
        // throw exception if no target or target not a data node
        ListIterator&   Remove(const ListIterator& _it);

        // return true if list is empty ,else false
        bool            Empty()const;


    private:

        List* m_list;//c List
};

#endif // __LISTCPP__
